package com.example.gateway.listener;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingFactory;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.listener.NamingEvent;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.example.gateway.cluster.ClusterManager;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.*;
import java.util.stream.Collectors;
import static com.example.gateway.constant.Constant.SERVER_NAME;

/**
 * @author 谢飞机
 * @date   2021-09-20
 */
@Component
public class RegistrationCenterChangeEventListener implements EventListener {


    /**
     * 注册中心变化监听器
     * 本类使用Nacos 提供的java SDK监听nacos服务节点上下线事件nacos上下线以后更新本地Hash环
     * TODO 如果可以的话 最好在nacos的上下线 修改hash环 然后利用redis 或者 mq 发布订阅即可
     * 当监听到变化更新哈希环
     * 需要注意：尽可能Nacos心跳时间配置及服务快速上下线
     * 思路：
     * 1、nacos 配置
     * 此方法打断点
     * com.alibaba.cloud.nacos.registry.NacosServiceRegistry#getNacosInstanceFromRegistration(org.springframework.cloud.client.serviceregistry.Registration)
     * 可以观察到
     * com.alibaba.nacos.api.naming.PreservedMetadataKeys
     * 中的常量
     * preserved.register.source
     * 文档里并没有看到与此有关的设置！！
     * 2、负载均衡配置
     */

    @Value("${spring.cloud.nacos.discovery.server-addr}")
    private String discoveryServerListList;

    @Value("spring.cloud.nacos.discovery.group")
    private String groupName;

    private final Log log = LogFactory.getLog(RegistrationCenterChangeEventListener.class);

    @Autowired
    private ClusterManager clusterManager;

    private NamingService namingService;

    private List<String> clusters;

    /**
     * key serverId  value 服务实例
     */

    public RegistrationCenterChangeEventListener() {

    }

    @Override
    @PostConstruct
    public void addListener() {

        try {

            clusters = Arrays.asList(discoveryServerListList.split(","));

            this.namingService = NamingFactory.createNamingService(discoveryServerListList);

            /**
             * namingService.getServerStatus()此状态是nacos服务的状态,不是某个服务实例的状态
             */

            namingService.subscribe(SERVER_NAME, event -> {

                if (event instanceof NamingEvent) {

                    NamingEvent namingEvent = (NamingEvent) event;

                    log.info("- - - - - - - - - 监听到服务实例【" + SERVER_NAME + "】变化事件 - - - - - - - - - ");

                    List<String> serverIpList =namingEvent.getInstances().stream().collect(Collectors.mapping(Instance::getIp,Collectors.toList()));

                    clusterManager.refresh(serverIpList);
                }
            });
        } catch (NacosException e) {
            e.printStackTrace();
        }
    }


}
